#include <iostream>

// 定制删除器unique_ptr
template <class T>
struct default_delete
{
    void operator()(T *ptr)
    {
        if (ptr)
        {
            delete ptr;
            ptr = nullptr;
        }
    }
};

template <class T, class Deleter = default_delete<T>>
class unique_ptr
{
public:
    unique_ptr(T *ptr = nullptr)
        : _ptr(ptr)
    {
    }
    ~unique_ptr() { _del(_ptr); }
    unique_ptr(const unique_ptr<T> &up) = delete;
    unique_ptr<T> &operator=(const unique_ptr<T> &up) = delete;

    unique_ptr(unique_ptr<T> &&up)
        : _ptr(up._ptr), _del(std::move(up._del))
    {
        up._ptr = nullptr;
    }

    // unique_ptr<T> &operator=(unique_ptr<T> &&up)
    // {
    //     if (this != &up)
    //     {
    //         _del(_ptr);
    //         _ptr = up._ptr;
    //         _del = std::move(up._del);
    //         up._ptr = nullptr;
    //     }
    //     return *this;
    // }

    unique_ptr<T> &operator=(unique_ptr<T> &&up)
    {
        if (this != &up)
        {
            this->swap(up);
        }
        return *this;
    }

    void reset(T *ptr = nullptr)
    {
        unique_ptr<T, Deleter>().swap(*this);
        _ptr = ptr;
    }

    void swap(unique_ptr<T> &up) noexcept
    {
        std::swap(_ptr, up._ptr);
        std::swap(_del, up._del);
    }

    operator bool() { return _ptr != nullptr; }

    T *operator->() const { return _ptr; }
    T &operator*() const { return *_ptr; }
    T *get() { return _ptr; }

private:
    T *_ptr;
    Deleter _del;
};

int main()
{
    int *raw_ptr = new int(42);
    int *raw_ptr1 = new int(40);
    unique_ptr<int> up1(raw_ptr);
    unique_ptr<int> up2 = std::move(up1);

    std::cout << *up2 << std::endl;
    up2.reset(raw_ptr1);
    std::cout << *up2 << std::endl;
    return 0;
}